package cz.byteworks.android.myway.location;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;

import android.content.Context;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.widget.Toast;
import cz.byteworks.android.myway.db.DataHelper;
import cz.byteworks.android.myway.pojo.Position;
import cz.byteworks.android.myway.util.NowButtonTextTask;

public class MyWayLocationListener implements LocationListener {

	private LocationManager _locationManager;
	private DataHelper _dataHelper;
	private Context _context;
	private Position lastPos;

	public MyWayLocationListener(Context context, LocationManager locationManager, DataHelper dataHelper, Position latestPosition) {
		this._locationManager = locationManager;
		this._dataHelper = dataHelper;
		this._context = context;
		this.lastPos = latestPosition;
	}

	public synchronized void onLocationChanged(Location location) {
		// ziskame nastaveni aplikace
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(_context);
		// ukladame pouze polohu odlisnou od posledni, pokud si tak uzivatel nastavi
		if (prefs.getBoolean("onlyDistinct", true)) {
			if (lastPos != null && lastPos.getLatitude() == location.getLatitude() && lastPos.getLongitude() == location.getLongitude()) {
				return;
			}
		}
		String provider = location.getProvider();
		// zrusime registraci zjistovani polohy
		_locationManager.removeUpdates(this);
		Position position = new Position();
		position.setLatitude(location.getLatitude());
		position.setLongitude(location.getLongitude());
		position.setLocateTime(new Date());
		position.setAltitude(location.getAltitude());
		// do pozice si poznamename, ktery provider nam polohu poskytl
		// tuto informaci pak budeme ukazovat uzivateli
		if (LocationManager.GPS_PROVIDER.equals(provider)) {
			position.setMark(1);
		}
		else if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
			position.setMark(2);
		}
		else {
			position.setMark(0);
		}
		
		// zjistime lokalitu, pokud si tak uzivatel nastavi
		getLocality(position, prefs);
		// ulozime pozici do databaze
		_dataHelper.insertPosition(position);
		AutoLocator.setLocating(false);
		if (prefs.getBoolean("vibrate", false)) {
			Vibrator vibrator = (Vibrator) _context.getSystemService(Context.VIBRATOR_SERVICE);
			vibrator.vibrate(700);
		}
		// naplanujeme zmenu textu na widgetu
		scheduleButtonTextChange(_context);
		// zobrazime hlasku o ulozeni pozice
		Toast.makeText(_context, "Position saved", 4000).show();
	}
	
	private void getLocality(Position position, SharedPreferences prefs) {
		if (prefs.getBoolean("locality", false)) {
			ConnectivityManager conManager = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
			if (conManager.getActiveNetworkInfo() != null && conManager.getActiveNetworkInfo().isAvailable()) {
				Geocoder gc = new Geocoder(_context, Locale.getDefault());
				String locality = "";
				try {
					List<Address> addresses = gc.getFromLocation(position.getLatitude(), position.getLongitude(), 1);
					if (addresses != null && addresses.size() > 0) {
						Address addr = addresses.get(0);
						if (addr.getAddressLine(0) != null) {
							locality = locality + addr.getAddressLine(0);
						}
						if (addr.getLocality() != null) {
							if (locality.length() > 0) {
								if (locality.length() > 21) {
									locality = locality + ",\n" + addr.getLocality();
								}
								else {
									locality = locality + ", " + addr.getLocality();
								}
							} else {
								locality = locality + addr.getLocality();
							}
						}
						if (locality.length() == 0 && addr.getAdminArea() != null) {
							locality = locality + addr.getAdminArea();
						}
						if (addr.getCountryCode() != null)
							if (locality.length() > 0) {
								locality = locality + " (" + addr.getCountryCode() + ")";
							} else {
								if (addr.getCountryName() != null) {
									locality = locality + addr.getCountryName();
								}
							}
						position.setLocality(locality);
					}
				} catch (IOException e) {
				}
			}
		}
	}

	public void onProviderDisabled(String provider) {
		if (!_locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !_locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
			AutoLocator.stopLocating(_context);
		}
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
	}
	
	private static void scheduleButtonTextChange(Context ctx) {
		Timer timer = new Timer();
		NowButtonTextTask task = new NowButtonTextTask(ctx, timer);
		timer.schedule(task, new Date(), 100);
	}

}
